﻿#pragma once

#include <string>
#include "glm/glm.hpp"

#include "core/Macro.h"
#include "function/RenderSystem/AbstractShader.h"


namespace Engine
{
	class ENGINE_API OpenGLShader final : public AbstractShader
	{
	public:
		explicit OpenGLShader(const std::string& filePath);
		OpenGLShader(std::string name, const std::string& vertexSrc, const std::string& fragmentSrc);
		~OpenGLShader() override;

		[[nodiscard]] const std::string& GetName() const override { return name; }

		void Bind() const override;
		void UnBind() const override;

		void SetVec2(const std::string& name, const glm::vec2& value) override;
		void SetFloat2(const std::string& name, float x, float y) const;
		void SetVec3(const std::string& name, const glm::vec3& value) override;
		void SetFloat3(const std::string& name, float x, float y, float z) const;
		void SetVec4(const std::string& name, const glm::vec4& value) override;
		void SetFloat4(const std::string& name, float x, float y, float z, float w) const;

		void SetUniformInt(const std::string& name, int value) const;
		void SetUniformIntArray(const std::string& name, int* values, unsigned int count) override;
		void SetUniformFloat(const std::string& name, float value) const;
		void SetUniformMat2(const std::string& name, const glm::mat2& matrix) const override;
		void SetUniformMat3(const std::string& name, const glm::mat3& matrix) const override;
		void SetUniformMat4(const std::string& name, const glm::mat4& matrix) const override;

	private:
		unsigned int rendererID;
		std::string name;

		static std::string ReadFile(const std::string& filePath);
		static std::unordered_map<unsigned int, std::string> PreProcess(const std::string& source);
		void Compile(std::unordered_map<unsigned int, std::string>& shaderSourceCode);
	};
}
